﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIA.Integration;
using VIA.Integration.Alarms;

namespace VIA.SiMoJi.Domain.Electronics
{
    public class CylinderEx : Cylinder, ISuportClearAlarm
    {
        public static int Timeout = 3000;

        private bool _isPushOutError;
        private bool isTakeBackError;
        private bool _isMoveError;
        public IoPoint PushOutSensor { get; private set; }
        public IoPoint BackSensor { get; private set; }

        [Alarm(true, AlarmLevel.Error, Description = "气缸伸出异常")]
        public bool IsPushOutError { get => _isPushOutError; set => this.NotifyAlarm(ref _isPushOutError, value); }

        [Alarm(true, AlarmLevel.Error, Description = "气缸缩回异常")]
        public bool IsTakeBackError { get => isTakeBackError; set => this.NotifyAlarm(ref isTakeBackError, value); }

        [Alarm(true, AlarmLevel.Error, Description = "气缸安全条件限制不能操作")]
        public bool IsMoveError { get => _isMoveError; set => this.NotifyAlarm(ref _isMoveError, value); }

        public CylinderEx(IoPoint pushIo) : base(pushIo)
        {
            this.InitalizeAlarms();
        }

        public CylinderEx(IoPoint pushIo, IoPoint backIo) : base(pushIo, backIo)
        {
            this.InitalizeAlarms();
        }

        public CylinderEx(IoPoint pushIo, IoPoint backIo, IoPoint pushStatusIO, IoPoint backStatusIO) : base(pushIo, backIo)
        {
            this.InitalizeAlarms();
            PushOutSensor = pushStatusIO;
            BackSensor = backStatusIO;
        }

        public async Task<bool> PushOutAsync(int waitDelay = 500, CancellationToken token = default, int timeout = 3000, int interval = 50)
        {
            if (!await IsCheckCanMoveAsync()) return false;
            PushOut();
            if (waitDelay > 0)
                await Task.Delay(waitDelay);
            if (await Judger.Sure(IsPushOut, token, timeout, interval))
            {
                await Task.Delay(200);
                return true;
            }
            else
            {
                IsPushOutError = true;
                return false;
            }
        }
        public async Task<bool> PushOutAsync2(CancellationToken cancellationToken = default, int timeout = 3000, int arriveTime = 200, int interval = 50)
        {
            if (!await IsCheckCanMoveAsync()) return false;
            PushOut();
            if (await Judger.Sure(IsPushOut, cancellationToken, timeout, interval))
            {
                if (arriveTime > 0)
                    await Task.Delay(arriveTime, cancellationToken);
                return true;
            }
            else
            {
                IsPushOutError = true;
                await Task.Delay(interval, cancellationToken);
                return false;
            }
        }
        public async Task<bool> TakeBackAsync(int waitDelay = 500, CancellationToken token = default, int timeout = 3000, int interval = 50)
        {
            if (!await IsCheckCanMoveAsync()) return false;
            TakeBack();
            if (waitDelay > 0)
                await Task.Delay(waitDelay);
            if (await Judger.Sure(IsBack, token, timeout, interval))
            {
                await Task.Delay(200);
                return true;
            }
            else
            {
                IsTakeBackError = true;
                return false;
            }
        }
        public async Task<bool> TakeBackAsync2(CancellationToken cancellationToken = default, int timeout = 3000, int arriveTime = 200, int interval = 50)
        {
            if (!await IsCheckCanMoveAsync()) return false;
            TakeBack();
            if (await Judger.Sure(IsBack, cancellationToken, timeout, interval))
            {
                if (arriveTime > 0)
                    await Task.Delay(arriveTime, cancellationToken);
                return true;
            }
            else
            {
                IsTakeBackError = true;
                await Task.Delay(interval, cancellationToken);
                return false;
            }
        }

        /// <summary>
        /// 检测气缸磁环开关是否伸出到位
        /// </summary>
        /// <returns></returns>
        public bool IsPushOut()
        {
            if (PushOutSensor != null && BackSensor != null)
            {
                return PushOutSensor.Value && !BackSensor.Value;
            }
            else if (PushOutSensor != null)
            {
                return PushOutSensor.Value;
            }
            else if (BackSensor != null)
            {
                return !BackSensor.Value;
            }
            else
            {
                return State == CylinderStates.PushOut;
            }
        }

        /// <summary>
        /// 检测气缸磁环开关是否缩回到位
        /// </summary>
        /// <returns></returns>
        public bool IsBack()
        {
            if (PushOutSensor != null && BackSensor != null)
            {
                return !PushOutSensor.Value && BackSensor.Value;
            }
            else if (PushOutSensor != null)
            {
                return !PushOutSensor.Value;
            }
            else if (BackSensor != null)
            {
                return BackSensor.Value;
            }
            else
            {
                return State == CylinderStates.TakeBack;
            }
        }

        public void ClearAlarm()
        {
            IsPushOutError = false;
            IsTakeBackError = false;
            IsMoveError = false;
        }
        public Func<bool> CanMove;
        /// <summary>
        /// 检测气缸是否在安全条件下操作
        /// </summary>
        /// <returns></returns>
        protected async Task<bool> IsCheckCanMoveAsync()
        {
            if (CanMove != null)
            {
                if (!CanMove.Invoke())
                {
                    if (!_isMoveError)
                        IsMoveError = true;
                    await Task.Delay(1000);
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// 校验状态是否一致
        /// </summary>
        /// <param name="states"></param>
        /// <returns></returns>
        public bool VerifyState(CylinderStates states)
        {
            if (states == CylinderStates.PushOut)
            {
                return IsPushOut();
            }
            else if (states == CylinderStates.TakeBack)
            {
                return IsBack();
            }
            return true;
        }
        /// <summary>
        /// 执行状态恢复
        /// </summary>
        /// <param name="states"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task RecoveryState(CylinderStates states, CancellationToken cancellationToken)
        {
            if (states == CylinderStates.PushOut)
            {
                await PushOutAsync2(cancellationToken);
            }
            else if (states == CylinderStates.TakeBack)
            {
                await TakeBackAsync2(cancellationToken);
            }
        }
    }
}
